﻿using TwlPhy;
using System;
using TwlAction;
using System.Collections.Generic;

/// <summary>
/// 实体基类
/// 碰撞不再使用Unity
/// </summary>
public class BaseEntity : IDispose
{
    #region action 
    private Dictionary<int, BaseAction> actionMap = new Dictionary<int, BaseAction>();

    public void addAction(BaseAction action)
    {
        if (!actionMap.ContainsKey(action.actionData.actionGuid))
        {
            actionMap.Add(action.actionData.actionGuid, action);
        }
    }
    public void removeAction(BaseAction action)
    {
        if (actionMap.ContainsKey(action.actionData.actionGuid))
        {
            actionMap.Remove(action.actionData.actionGuid);
        }
    }
    public void removeAllAction()
    {
        actionMap.Clear();
    }
    public Dictionary<int, BaseAction> getAllAction() {
        return actionMap;
    }
    #endregion
    private float realSpeed = 3f;
    public float speed
    {
        get
        {
            return moveDir.y != 0 ? realSpeed / 2 : realSpeed;
        }
        set
        {
            realSpeed = value;
        }
    }
    public float jumpHeight = 4f;

    ////移动相关
    public Vector2 moveVec = Vector2.zero;
    protected Vector2 dir = Vector2.zero;
    public virtual Vector2 moveDir
    {
        get
        {
            return dir;
        }
        set
        {
            dir = value;
        }
    }

    public LookFlag lookFlag = LookFlag.Right;
    //状态机
    protected FSM fsm;
    private FSM_Flag flag = FSM_Flag.None;
    public FSM_Flag Flag
    {
        get
        {
            return flag;
        }
        set
        {
            flag = value;
        }
    }

    private RoleData roleData = null;
    public RoleData RoleData
    {
        get
        {
            return roleData;
        }
        set
        {
            roleData = value;
            initData();
        }
    }
    //加载状态
    private E_EntityLoadState loadState = E_EntityLoadState.Waiting;
    public E_EntityLoadState LoadState
    {
        get
        {
            return this.loadState;
        }
    }

    public long UID
    {
        get
        {
            return this.roleData.uid;
        }
    }

    //移动碰撞盒
    protected DymicBox3D dyBox;
    public DymicBox3D DyBox
    {
        get
        {
            return dyBox;
        }
    }
    //受击碰撞盒
    private DymicBox3D hitBox;
    public DymicBox3D HitBox
    {
        get
        {
            return hitBox;
        }
    }

    /// <summary>
    /// 接口 播放动画
    /// </summary>
    /// <param name="anim"></param>
    /// <param name="loop"></param>
    /// <param name="add"></param>
    public float playAnim(string anim, bool loop = false, string add = null, bool forcePlay = false)
    {
        if (ShowWidget != null)
            return ShowWidget.playAnim(anim, loop, add, forcePlay);
        return 0;
    }

    /// <summary>
    /// 修改动画完成订阅
    /// </summary>
    /// <param name="isAdd"></param>
    public void modifyCompleteEvent(bool isAdd)
    {
        if (ShowWidget != null)
        {
            ShowWidget.modifyCompleteEvent(isAdd);
        }
    }

    /// <summary>
    /// 接口改变朝向
    /// </summary>
    /// <param name="flag"></param>
    public void changeLookFlag(LookFlag flag)
    {
        if (this.lookFlag == flag) return;
        this.lookFlag = flag;
        if (ShowWidget != null)
        {
            ShowWidget.changeLookFlag(flag);
        }
    }

    /// <summary>
    /// 接口 转换状态
    /// </summary>
    /// <param name="flag"></param>
    /// <param name="args"></param>
    public void transFsm(FSM_Flag flag, FSMArgs args = null, bool forceTrans = false)
    {
        if (this.fsm != null)
        {
            bool isSuccess = this.fsm.transFsm(flag, args, forceTrans);
            if (isSuccess)
            {
                Flag = flag;
            }
        }
    }

    //逻辑帧tick
    public void Tick()
    {
        if (this.fsm != null)
        {
            this.fsm.tick();
        }
    }
    //渲染帧tick
    public void Render()
    {
        if (this.fsm != null)
        {
            this.fsm.onRender();
        }

#if UNITY_EDITOR
        if (this.ShowWidget != null)
        {
            this.ShowWidget.updateInspector();
        }
#endif
    }

    protected virtual void initFsm()
    {
        if (fsm == null)
        {
            fsm = new FSM(this);
            fsm.addState(FSM_Flag.Idle, new IdleState());
            fsm.addState(FSM_Flag.Run, new PhyRunState());
            fsm.addState(FSM_Flag.Jump, new JumpState());
            fsm.addState(FSM_Flag.JumpFall, new FallState());
            fsm.addState(FSM_Flag.AirFall, new AirFallState());
            fsm.addState(FSM_Flag.Hit, new HitState());
            fsm.addState(FSM_Flag.StandHit, new StandHitState());
            fsm.addState(FSM_Flag.AirHit, new AirHitState());
            fsm.addState(FSM_Flag.CurveHit, new CurveHitState());
            fsm.addState(FSM_Flag.Stiff, new StiffState());
        }
    }

    protected void doRun()
    {
        transFsm(FSM_Flag.Run);
    }

    public void updateRenderOrder()
    {
        if (this.ShowWidget != null)
        {
            ShowWidget.updateRenderOrder();
        }
        if (this.BillboardWidget != null)
        {
            BillboardWidget.updateRenderSort();
        }
    }

    protected virtual void initData()
    {
        //fsm
        initFsm();
        //刷新数据
        refresh();
        //其他初始化
        onStart();
    }

    /// <summary>
    /// 刷新实体函数
    /// 初始化和实体数据被编辑的时候 刷新整个实体
    /// </summary>
    public virtual void refresh()
    {
        //look 
        this.lookFlag = RoleData.lookFlag;
        //速度 跳跃速度
        this.speed = RoleData.speed;
        this.jumpHeight = RoleData.jumpSpeed;
        //碰撞器位置和大小
        dyBox = new DymicBox3D(RoleData.pos.x, RoleData.pos.y, RoleData.pos.z, RoleData.moveBox.x, RoleData.moveBox.y, RoleData.moveBox.z);
        hitBox = new DymicBox3D(RoleData.pos.x, RoleData.pos.y, RoleData.pos.z, RoleData.hitBox.x, RoleData.hitBox.y, RoleData.hitBox.z);
        //默认状态
        transFsm(FSM_Flag.Idle);
        //客户读创建显示
        createDisplay();
    }

    //客户端相关
    //实体展示 包括mesh
    private RoleShowWidget showWidget;
    public RoleShowWidget ShowWidget
    {
        get
        {
            return showWidget;
        }
        set
        {
            showWidget = value;
        }
    }
    //姓名版 
    private BillboardWidget billboardWidget;
    public BillboardWidget BillboardWidget
    {
        get
        {
            return billboardWidget;
        }
        set
        {
            billboardWidget = value;
        }
    }


    private UnityEngine.GameObject unityObj = null;
    private void createDisplay()
    {
        //Unity相关物件挂载点
        if (unityObj == null)
        {
            unityObj = new UnityEngine.GameObject(UID.ToString());
        }
        //模型组件
        if (ShowWidget == null)
        {
            ShowWidget = unityObj.AddComponent<RoleShowWidget>();
            ShowWidget.changeLookFlag(this.lookFlag);
            ShowWidget.setAgent(this);
        }
        else
        {
            ShowWidget.refresh();
        }
        if (BillboardWidget == null)
        {
            BillboardWidget = unityObj.AddComponent<BillboardWidget>();
            BillboardWidget.setAgent(this);
            BillboardWidget.createBoard();
        }
    }

    protected virtual void onStart()
    {

    }

    public void doMove(Vector2 dir)
    {
        dyBox.AddCenter(dir.x, dir.y);
        hitBox.AddCenter(dir.x, dir.y);
        if (ShowWidget != null)
        {
            ShowWidget.doMove();
        }
    }
    public void doMove(float x, float y)
    {
        dyBox.AddCenter(x, y);
        hitBox.AddCenter(x, y);
        if (ShowWidget != null)
        {
            ShowWidget.doMove();
        }
    }
    public void updatePosHeight(float posZ)
    {
        dyBox.updatePosHeight(posZ);
        hitBox.updatePosHeight(posZ);
        if (ShowWidget != null)
        {
            ShowWidget.doMove();
        }
    }

    public void kickMove(Vector2 target)
    {
        dyBox.UpdateCenter(target.x, target.y);
        hitBox.UpdateCenter(target.x, target.y);
        if (ShowWidget != null)
        {
            ShowWidget.doMove();
        }
    }

    /// <summary>
    /// 清理 回收
    /// </summary>
    public void onDispose()
    {
        if (ShowWidget != null)
        {
            ShowWidget.onDispose();
        }
        //回收data
        Pool.PoolMgr.Instance.recyleData(roleData);
        this.roleData = null;
    }
}
